#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/msg.h>

#define N 128

typedef struct msg
{
    long mtype;    /* message type, must be > 0 */
    char mtext[N]; /* message data */
} msg_t;

int main(int argc, char const *argv[])
{
    int ret;
    msg_t msg;
    memset(&msg, 0, sizeof(msg)); // 初始化结构体中所有的成员
    // 生成一个IPC 唯一key值
    // 因为shm 用了/home , 1 参数, 此时需要设置一个不一样的, 要不然会冲突
    key_t key = ftok("/home", 2);
    if (key < 0)
    {
        perror("ftok");
        exit(-1);
    }
    printf("key=%#x\n", key);
    int msgid = msgget(key, IPC_CREAT | 0664); // 如果不存在就创建, 存在就打开
    if (msgid < 0)
    {
        perror("msgget");
        exit(-1);
    }
    printf("msgid=%d\n", msgid);
    system("ipcs -q"); // 执行linux系统的一个命令 ,  查看系统的消息队列

    pid_t pid = fork();
    if (pid < 0)
    {
        perror("fork");
        exit(-1);
    }
    else if (pid == 0) // 子进程
    {
        msg.mtype = 'B';

        while (1)
        {
            printf(">:");
            fgets(msg.mtext, N, stdin);
            msg.mtext[strlen(msg.mtext) - 1] = 0;            // 消除 '\n'
            ret = msgsnd(msgid, &msg, sizeof(msg.mtext), 0); // 往消息队列中发送一个消息
            if (ret < 0)
            {
                perror("msgsnd");
                exit(-1);
            }
        }
    }
    else // 父进程
    {

        while (1)
        {
            ret = msgrcv(msgid, &msg, sizeof(msg.mtext), 'A', 0);
            if (ret < 0)
            {
                perror("msgrcv");
                exit(-1);
            }
            // printf("msg.mtype=%c\n", (char)msg.mtype);
            printf("msg.mtext=%s\n", msg.mtext);
            memset(&msg, 0, sizeof(msg));
        }
    }

    system("ipcs -q");                   // 执行linux系统的一个命令 ,  查看系统的消息队列
    ret = msgctl(msgid, IPC_RMID, NULL); // 删除消息队列
    if (ret < 0)
    {
        perror("msgctl");
        exit(-1);
    }
    system("ipcs -q"); // 执行linux系统的一个命令 ,  查看系统的消息队列

    return 0;
}